package projects

import (
	"errors"
	"github.com/beego/beego/v2/client/orm"
	"time"
	"xpms/app/cases"
	"xpms/app/models"
	"xpms/cores"
	"xpms/cores/utils"
	"xpms/cores/utils/stream"
)

type TaskCase struct {
	Id            int64 `orm:"pk;column(id);" json:"Id,string"`
	Projectid     int64 `json:"Projectid,string"`
	Planid        int64 `json:"Planid,string"`
	Taskid        int64 `json:"Taskid,string"`
	Taskrelid     int64 `json:"Taskrelid,string"`
	Caseid        int64 `json:"Caseid,string"`
	Moduleid      int64 `json:"Moduleid,string"`
	Name          string
	Type          int64
	Degree        int64
	Version       int64 `json:"Version,string"`
	Preconditions string
	Remarks       string
	Attachment    string
	Created       int64
	Createid      int64 `json:"Createid,string"`
	Status        int
	Changed       int64
	Changid       int64 `json:"Changid,string"`
	Planstatus    int
	Executor      int64 `json:"Executor,string"`
	Executorname  string
}

func (this *TaskCase) TableName() string {
	return models.TableName("projects_task_case")
}

func init() {
	orm.RegisterModel(new(TaskCase))
}

type AddTaskCaseDto struct {
	Taskid  int64   `json:"Taskid,string"`
	Related []int64 `json:"Related,string"`
}

/**
  添加任务对应的测试包
*/
func AddTaskCase(userid int64, username string, upd AddTaskCaseDto) error {
	var err error
	if utils.IsEmpty(upd.Related) {
		return errors.New("没有对应的关联id")
	}
	if utils.IsEmpty(upd.Taskid) {
		return errors.New("任务id不存在")
	}
	condArr := make(map[string]interface{})
	condArr["pkgid"] = upd.Related
	ops := cases.CaseByPkg(condArr)
	if utils.IsEmpty(ops) {
		return errors.New("没有对应的用例包编号")
	}
	caseStep, err := cases.TaskCaseStepByCaseIds(condArr)
	if utils.IsEmpty(caseStep) || err != nil {
		return errors.New("没有对应用例没有执行步骤")
	}
	stream, _ := stream.New(caseStep)
	task, err := GetProjectTask(upd.Taskid)
	if err != nil {
		return err
	}
	var u []TaskCase
	var uStep []TaskCaseStep
	var taskRel []ProjectTaskRelated
	utils.UUID.Init(1024)
	for _, v := range ops {
		tr := new(ProjectTaskRelated)
		rid, _ := utils.UUID.GetId()
		tr.Id = rid
		tr.Taskid = task.Id
		tr.Related = v.Pkgid
		tr.Type = 6
		tr.Created = time.Now().Unix()
		taskRel = append(taskRel, *tr)
		tid, _ := utils.UUID.GetId()
		tc := new(TaskCase)
		utils.SimpleCopyProperties(tc, v)
		tc.Id = tid
		tc.Projectid = task.Projectid
		tc.Planid = task.Planid
		tc.Createid = userid
		tc.Changid = userid
		tc.Changed = time.Now().Unix()
		tc.Created = time.Now().Unix()
		tc.Taskrelid = rid
		u = append(u, *tc)
		var caseStep []cases.TestCaseStep
		stream.Filter(func(s cases.TestCaseStep) bool {
			return s.Caseid == tc.Caseid
		}).ToSlice(&caseStep)
		for _, v := range caseStep {
			tcs := new(TaskCaseStep)
			utils.SimpleCopyProperties(tcs, v)
			id, _ := utils.UUID.GetId()
			tcs.Id = id
			tcs.Planid = task.Planid
			tcs.Taskid = task.Testid
			tcs.Taskcaseid = tid
			tcs.Taskrelid = rid
			tcs.Createid = userid
			tcs.Changid = userid
			tcs.Changname = username
			tcs.Changed = time.Now().Unix()
			tcs.Created = time.Now().Unix()
			uStep = append(uStep, *tcs)
		}

	}
	/**
	  开始保存数据
	*/
	o := orm.NewOrm()
	to, err := o.Begin()
	_, err = to.InsertMulti(100, taskRel)
	if err != nil {
		to.Rollback()
		return err
	}
	_, err = to.InsertMulti(100, u)
	if err != nil {
		to.Rollback()
		return err
	}
	_, err = to.InsertMulti(100, uStep)
	if err != nil {
		to.Rollback()
		return err
	}
	if err == nil {
		to.Commit()
	}
	return err
}

type DelTaskCaseDto struct {
	TaskRelated []int64 `json:"TaskRelated,string"`
}

/**
  添加任务对应的测试包
*/
func DelTaskCase(upd DelTaskCaseDto) error {
	if utils.IsEmpty(upd.TaskRelated) {
		return errors.New("没有对应的关联id")
	}
	o := orm.NewOrm()
	to, err := o.Begin()

	sql := `  DELETE tcs  FROM pms_projects_task_case_step tcs 
         INNER JOIN  pms_projects_task_case tc ON tc.id=tcs.taskcaseid
         INNER JOIN pms_projects_task_related pptr ON pptr.related=tc.taskrelid WHERE  `
	param := make([]interface{}, 0, 0)
	sql = sql + `  pptr.id in(`
	sql1, value := cores.SqlInParam(upd.TaskRelated)
	sql = sql + sql1 + `)`
	param = append(param, value...)
	_, err = to.Raw(sql, param).Exec()
	if err != nil {
		to.Rollback()
		return err
	}
	sql = ` DELETE tc  FROM pms_projects_task_case tc INNER JOIN pms_projects_task_related pptr ON pptr.related=tc.taskrelid WHERE  `
	param = make([]interface{}, 0, 0)
	sql = sql + `  pptr.id in(`
	sql1, value = cores.SqlInParam(upd.TaskRelated)
	sql = sql + sql1 + `)`
	param = append(param, value...)
	_, err = to.Raw(sql, param).Exec()
	if err != nil {
		to.Rollback()
		return err
	}
	sql = `DELETE pms_projects_task_related WHERE `
	param = make([]interface{}, 0, 0)
	sql = sql + ` id in(`
	sql1, value = cores.SqlInParam(upd.TaskRelated)
	sql = sql + sql1 + `)`
	param = append(param, value...)
	_, err = to.Raw(sql, param).Exec()
	if err != nil {
		to.Rollback()
		return err
	}
	if err == nil {
		to.Commit()
	}
	return err
}

type UpdateTaskCaseStepDto struct {
	Id            int64 `json:"id,string"`
	Actionresults string
	Status        int   `json:"Status,string"`
	TaskCaseid    int64 `json:"TaskCaseid,string"`
}

func UpdateTaskCaseStep(userid int64, username string, upd []UpdateTaskCaseStepDto) error {
	o := orm.NewOrm()
	to, err := o.Begin()
	for _, v := range upd {
		tcs := new(TaskCaseStep)
		tcs.Changed = time.Now().Unix()
		tcs.Changid = userid
		tcs.Changname = username
		tcs.Status = v.Status
		tcs.Actionresults = v.Actionresults
		tcs.Id = v.Id
		_, err = to.Update(&tcs, "changid", "changedname", "actionresults", "status")
		if err != nil {
			to.Rollback()
			return err
		}
		tc := new(TaskCase)
		tc.Id = v.TaskCaseid
		tc.Changed = time.Now().Unix()
		tc.Changid = userid
		tc.Executor = userid
		tc.Executorname = username
		_, err = to.Update(&tc, "changid", "changedname", "executor", "executorname")
		if err != nil {
			to.Rollback()
			return err
		}
	}
	if err == nil {
		to.Commit()
	}
	return err
}

type UpdateTaskCaseDto struct {
	Id     int64 `json:"id,string"`
	Status int   `json:"Status,string"`
}

func UpdateTaskCase(userid int64, username string, upd UpdateTaskCaseDto) error {
	if utils.IsEmpty(upd.Id) {
		return errors.New("没有对应的任务caseid")
	}
	tc := new(TaskCase)
	o := orm.NewOrm()
	tc.Id = upd.Id
	tc.Changed = time.Now().Unix()
	tc.Changid = userid
	tc.Executor = userid
	tc.Executorname = username
	tc.Planstatus = upd.Status
	_, err := o.Update(&tc, "changid", "changedname", "executor", "executorname", "planstatus")
	if err != nil {
		return err
	}
	return nil
}

type QueryTaskCasePkgDto struct {
	Id         int64 `json:"id,string"`
	Status     int   `json:"Status,string"`
	Name       string
	Acceptname string
}

func QueryTaskCasePkgByTaskId(id int64) []QueryTaskCasePkgDto {
	o := orm.NewOrm()
	var dto []QueryTaskCasePkgDto
	sql := `SELECT tr.id,pkg.name,pkg.acceptname,pkg.status
            FROM pms_projects_task_related tr INNER JOIN pms_projects_test_case_pkg pkg ON  tr.type=6 AND tr.related=pkg.id  WHERE tr.taskid=?`
	o.Raw(sql, id).QueryRows(&dto)
	return dto
}

type QueryTaskCaseDto struct {
	Id            int64 `orm:"pk;column(id);" json:"Id,string"`
	Projectid     int64 `json:"Projectid,string"`
	Planid        int64 `json:"Planid,string"`
	Taskid        int64 `json:"Taskid,string"`
	Taskrelid     int64 `json:"Taskrelid,string"`
	Caseid        int64 `json:"Caseid,string"`
	Moduleid      int64 `json:"Moduleid,string"`
	Name          string
	Type          int64
	Degree        int64
	Version       int64 `json:"Version,string"`
	Preconditions string
	Remarks       string
	Attachment    string
	Created       int64
	Createid      int64 `json:"Createid,string"`
	Status        int
	Changed       int64
	Changid       int64 `json:"Changid,string"`
	Planstatus    int
	Executor      int64 `json:"Executor,string"`
	Executorname  string
}

func QueryTaskCaseByTaskRelId(id int64) []QueryTaskCaseDto {
	o := orm.NewOrm()
	var dto []QueryTaskCaseDto
	sql := `SELECT tr.id,tc.* FROM pms_projects_task_related tr INNER JOIN pms_projects_task_case tc ON  tr.type=6 AND tr.related=tc.taskrelid  WHERE tr.id=?`
	o.Raw(sql, id).QueryRows(&dto)
	return dto
}
